﻿/* 
* Copyright (c) 2010, The University of Texas at Austin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation and/or other materials 
* provided with the distribution.
*
* Neither the name of The University of Texas at Austin nor the names of its contributors may be 
* used to endorse or promote products derived from this software without specific prior written 
* permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using Bio.Data;
using Bio.Data.Interfaces;
using Bio.Views.Structure.Editor.Internal.Rendering.Primitives;

namespace Bio.Views.Structure.Editor.Internal.Rendering.Visuals
{
    public class NucleotideStructureElementVisualComponentFactory
    {
        public static NucleotideStructureElementVisualComponent Create(NucleotideVector vectorToNextNucleotide, int index, IBioSymbol symbol)
        {
            Debug.Assert(symbol != null);
            Debug.Assert(index >= 0);
     
            //Check to see if any rendering properties have been specified on the individual nucleotide.
            IExtensibleProperties properties = symbol as IExtensibleProperties;
            if (properties != null)
            {
                if (properties.DoesExtendedPropertyExist(NucleotideMetadata.Key))
                {
                    NucleotideStructureElementVisualComponent ntVisual = new NucleotideStructureElementVisualComponent(vectorToNextNucleotide, symbol, index);
                    NucleotideMetadata metadata = properties.GetExtendedProperty<NucleotideMetadata>(NucleotideMetadata.Key);
                    
                    if(metadata.Visible.HasValue)
                        ntVisual.IsComponentVisible = metadata.Visible.Value;
                    
                    if (metadata.Style.HasValue && !(metadata.Style.Value == NucleotideMetadata.RenderingMode.Text || metadata.Style.Value == NucleotideMetadata.RenderingMode.Circle))
                    {
                        goto DefaultRendering; //Other rendering modes not supported for nucleotides yet.
                    }

                    if (metadata.Style.HasValue && metadata.Style.Value == NucleotideMetadata.RenderingMode.Text)
                        ntVisual.NucleotideRenderingStyle = NucleotideRenderingMode.Text;
                    else if (metadata.Style.HasValue && metadata.Style.Value == NucleotideMetadata.RenderingMode.Circle)
                        ntVisual.NucleotideRenderingStyle = NucleotideRenderingMode.Circle;
 
                    if (metadata.TextRendering != null)
                    {
                        //Lets see if we have valid values for any specified properties (the built in defaults are set, so if any fail we can skip them).
                        if (metadata.TextRendering.Font != null)
                        {
                            try { ntVisual.NucleotideFontFamily = (FontFamily)fontFamilyChecker.ConvertFrom(metadata.TextRendering.Font); }
                            catch { }
                        }

                        if (metadata.TextRendering.Color != null)
                        {
                            try { ntVisual.NucleotideFill = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.TextRendering.Color)); }
                            catch { }
                        }

                        if (metadata.TextRendering.FontStyle != null)
                        {
                            try { ntVisual.NucleotideFontStyle = (FontStyle)fontStyleChecker.ConvertFrom(metadata.TextRendering.FontStyle); }
                            catch { }
                        }

                        if (metadata.TextRendering.FontWeight != null)
                        {
                            try { ntVisual.NucleotideFontWeight = (FontWeight)fontWeightChecker.ConvertFrom(metadata.TextRendering.FontWeight); }
                            catch { }
                        }

                        if (metadata.TextRendering.FontSize > 0.0)
                            ntVisual.NucleotideFontSize = metadata.TextRendering.FontSize;

                        if (metadata.IsSubstituted)
                        {
                            ntVisual.IsNucleotideSubstituted = true;
                            ntVisual.NucleotideSubstitution = metadata.SubstitutionCharacter;
                        }
                    }
 
                    if (metadata.CircleRendering != null)
                    {
                        if (metadata.CircleRendering.Diameter > 0.0)
                            ntVisual.NucleotideCircleDiameter = metadata.CircleRendering.Diameter;

                        if (metadata.CircleRendering.EdgeThickness > 0.0)
                            ntVisual.NucleotideCircleEdgeThickness = metadata.CircleRendering.EdgeThickness;

                        if (metadata.CircleRendering.FillColor != null)
                        {
                            try { ntVisual.NucleotideCircleFill = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.CircleRendering.FillColor)); }
                            catch { }
                        }

                        if (metadata.CircleRendering.EdgeColor != null)
                        {
                            try { ntVisual.NucleotideCircleStroke = new SolidColorBrush((Color)colorChecker.ConvertFrom(metadata.CircleRendering.EdgeColor)); }
                            catch { }
                        }

                        ntVisual.NucleotideCircleIsFilled = metadata.CircleRendering.Filled;
                    }
                        
                    return ntVisual;
                }
                else
                {
                }
            }

            DefaultRendering:
            //If we reach here, were picking up the rendering from either a parent (base pair or the global structure model), accepting any defaults.
            return new NucleotideStructureElementVisualComponent(vectorToNextNucleotide, symbol, index);
        }

        private static double ConvertFontSizePointToEM(double fontSizeInPoints)
        {
            if (fontSizeInPoints < 0.0)
                throw new ArgumentException(string.Format("Invalid FontSize of {0} specified.", fontSizeInPoints));
            return (fontSizeInPoints * 96.0) / 72.0;
        }

        private static readonly FontFamilyConverter fontFamilyChecker = new FontFamilyConverter();
        private static readonly FontWeightConverter fontWeightChecker = new FontWeightConverter();
        private static readonly FontStyleConverter fontStyleChecker = new FontStyleConverter();
        private static readonly ColorConverter colorChecker = new ColorConverter();
    }
}
